<!DOCTYPE html>
<html CN>







<head>
	
	
	<link rel="stylesheet" href="/css/allinone.min.css"> 

	
	<!-- Global Site Tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-42863699-1"></script>
	<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());
		gtag('config', 'UA-42863699-1');
	</script>
	

	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />

	<title>serverless 平台 knative 简介 | Cizixs Write Here</title>

	<meta name="HandheldFriendly" content="True" />
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
	<meta name="generator" content="hexo">
	<meta name="author" content="Cizixs Wu">
	<meta name="description" content="">

	
	<meta name="keywords" content="">
	

	
	<link rel="shortcut icon" href="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg">
	

	
	<meta name="theme-color" content="#3c484e">
	<meta name="msapplication-TileColor" content="#3c484e">
	

	

	

	<meta property="og:site_name" content="Cizixs Write Here">
	<meta property="og:type" content="article">
	<meta property="og:title" content="serverless 平台 knative 简介 | Cizixs Write Here">
	<meta property="og:description" content="">
	<meta property="og:url" content="http://cizixs.com/2018/08/25/knative-serverless-platform/">

	
	<meta property="article:published_time" content="2018-08-25T00:08:00+08:00"/> 
	<meta property="article:author" content="Cizixs Wu">
	<meta property="article:published_first" content="Cizixs Write Here, /2018/08/25/knative-serverless-platform/" />
	

	
	
	<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
	

	
	<script src="https://cdn.staticfile.org/highlight.js/9.10.0/highlight.min.js"></script>
	

	
	
<link rel="stylesheet" href="/css/prism-base16-ateliersulphurpool.light.css" type="text/css"></head>
<body class="post-template">
    <div class="site-wrapper">
        




<header class="site-header outer" style="z-index: 999">
    <div class="inner">
        
<nav class="site-nav"> 
    <div class="site-nav-left">
        <ul class="nav">
            <li>
                
                <a href="/" title="Home">Home</a>
                
            </li>
            
            
            <li>
                <a href="/about" title="About">About</a>
            </li>
            
            <li>
                <a href="/archives" title="Archives">Archives</a>
            </li>
            
            
        </ul> 
    </div>
    <div class="site-nav-right">
        
<div class="social-links" >
    
    <a class="social-link" title="weibo" href="https://weibo.com/1921727853" target="_blank" rel="noopener">
        <svg viewBox="0 0 1141 1024" xmlns="http://www.w3.org/2000/svg"><path d="M916.48 518.144q27.648 21.504 38.912 51.712t9.216 62.976-14.336 65.536-31.744 59.392q-34.816 48.128-78.848 81.92t-91.136 56.32-94.72 35.328-89.6 18.944-75.264 7.68-51.712 1.536-49.152-2.56-68.096-10.24-78.336-21.504-79.872-36.352-74.24-55.296-59.904-78.848q-16.384-29.696-22.016-63.488t-5.632-86.016q0-22.528 7.68-51.2t27.136-63.488 53.248-75.776 86.016-90.112q51.2-48.128 105.984-85.504t117.248-57.856q28.672-10.24 63.488-11.264t57.344 11.264q10.24 11.264 19.456 23.04t12.288 29.184q3.072 14.336 0.512 27.648t-5.632 26.624-5.12 25.6 2.048 22.528q17.408 2.048 33.792-1.536t31.744-9.216 31.232-11.776 33.28-9.216q27.648-5.12 54.784-4.608t49.152 7.68 36.352 22.016 17.408 38.4q2.048 14.336-2.048 26.624t-8.704 23.04-7.168 22.016 1.536 23.552q3.072 7.168 14.848 13.312t27.136 12.288 32.256 13.312 29.184 16.384zM658.432 836.608q26.624-16.384 53.76-45.056t44.032-64 18.944-75.776-20.48-81.408q-19.456-33.792-47.616-57.344t-62.976-37.376-74.24-19.968-80.384-6.144q-78.848 0-139.776 16.384t-105.472 43.008-72.192 60.416-38.912 68.608q-11.264 33.792-6.656 67.072t20.992 62.976 42.496 53.248 57.856 37.888q58.368 25.6 119.296 32.256t116.224 0.512 100.864-21.504 74.24-33.792zM524.288 513.024q20.48 8.192 38.912 18.432t32.768 27.648q10.24 12.288 17.92 30.72t10.752 39.424 1.536 42.496-9.728 38.912q-8.192 18.432-19.968 37.376t-28.672 35.328-40.448 29.184-57.344 18.944q-61.44 11.264-117.76-11.264t-88.064-74.752q-12.288-39.936-13.312-70.656t16.384-66.56q13.312-27.648 40.448-51.712t62.464-38.912 75.264-17.408 78.848 12.8zM361.472 764.928q37.888 3.072 57.856-18.432t21.504-48.128-15.36-47.616-52.736-16.896q-27.648 3.072-43.008 23.552t-17.408 43.52 9.728 42.496 39.424 21.504zM780.288 6.144q74.752 0 139.776 19.968t113.664 57.856 76.288 92.16 27.648 122.88q0 33.792-16.384 50.688t-35.328 17.408-35.328-14.336-16.384-45.568q0-40.96-22.528-77.824t-59.392-64.512-84.48-43.52-96.768-15.872q-31.744 0-47.104-15.36t-14.336-34.304 18.944-34.304 51.712-15.36zM780.288 169.984q95.232 0 144.384 48.64t49.152 146.944q0 30.72-10.24 43.52t-22.528 11.264-22.528-14.848-10.24-35.84q0-60.416-34.816-96.256t-93.184-35.84q-19.456 0-28.672-10.752t-9.216-23.04 9.728-23.04 28.16-10.752z" /></svg>
    </a>
    

    
    <a class="social-link" title="github" href="https://github.com/cizixs" target="_blank" rel="noopener">
        <svg viewBox="0 0 1049 1024" xmlns="http://www.w3.org/2000/svg"><path d="M524.979332 0C234.676191 0 0 234.676191 0 524.979332c0 232.068678 150.366597 428.501342 358.967656 498.035028 26.075132 5.215026 35.636014-11.299224 35.636014-25.205961 0-12.168395-0.869171-53.888607-0.869171-97.347161-146.020741 31.290159-176.441729-62.580318-176.441729-62.580318-23.467619-60.841976-58.234462-76.487055-58.234463-76.487055-47.804409-32.15933 3.476684-32.15933 3.476685-32.15933 53.019436 3.476684 80.83291 53.888607 80.83291 53.888607 46.935238 79.963739 122.553122 57.365291 152.97411 43.458554 4.345855-33.897672 18.252593-57.365291 33.028501-70.402857-116.468925-12.168395-239.022047-57.365291-239.022047-259.012982 0-57.365291 20.860106-104.300529 53.888607-140.805715-5.215026-13.037566-23.467619-66.926173 5.215027-139.067372 0 0 44.327725-13.906737 144.282399 53.888607 41.720212-11.299224 86.917108-17.383422 131.244833-17.383422s89.524621 6.084198 131.244833 17.383422C756.178839 203.386032 800.506564 217.29277 800.506564 217.29277c28.682646 72.1412 10.430053 126.029806 5.215026 139.067372 33.897672 36.505185 53.888607 83.440424 53.888607 140.805715 0 201.64769-122.553122 245.975415-239.891218 259.012982 19.121764 16.514251 35.636014 47.804409 35.636015 97.347161 0 70.402857-0.869171 126.898978-0.869172 144.282399 0 13.906737 9.560882 30.420988 35.636015 25.205961 208.601059-69.533686 358.967656-265.96635 358.967655-498.035028C1049.958663 234.676191 814.413301 0 524.979332 0z" /></svg>
    </a>
    

    
    <a class="social-link" title="stackoverflow" href="https://stackoverflow.com/users/1925083/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15 21h-10v-2h10v2zm6-11.665l-1.621-9.335-1.993.346 1.62 9.335 1.994-.346zm-5.964 6.937l-9.746-.975-.186 2.016 9.755.879.177-1.92zm.538-2.587l-9.276-2.608-.526 1.954 9.306 2.5.496-1.846zm1.204-2.413l-8.297-4.864-1.029 1.743 8.298 4.865 1.028-1.744zm1.866-1.467l-5.339-7.829-1.672 1.14 5.339 7.829 1.672-1.14zm-2.644 4.195v8h-12v-8h-2v10h16v-10h-2z"/></svg>
    </a>
    

    

    
    <a class="social-link" title="twitter" href="https://twitter.com/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"/></svg>

    </a>
    

    
    <a class="social-link" title="instagram" href="https://www.instagram.com/cizixs/" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
    </a>
    
    
    
</div>
    </div>
</nav>
    </div>
</header>


<main id="site-main" class="site-main outer" role="main">
    <div class="inner">
        <header class="post-full-header">
            <section class="post-full-meta">
                <time  class="post-full-meta-date" datetime="2018-08-24T16:00:00.000Z" itemprop="datePublished">
                    2018-08-25
                </time>
                
                <span class="date-divider">/</span>
                
                <a href="/categories/blog/">blog</a>&nbsp;&nbsp;
                
                
            </section>
            <h1 class="post-full-title">serverless 平台 knative 简介</h1>
        </header>
        <article class="post-full no-image">
            
            <section class="post-full-content">
                <div id="lightgallery" class="markdown-body">
                    <h2 id="什么是-Knative？"><a href="#什么是-Knative？" class="headerlink" title="什么是 Knative？"></a>什么是 Knative？</h2><p><a href="https://github.com/knative" target="_blank" rel="noopener">knative</a> 是谷歌开源的 serverless 架构方案，旨在提供一套简单易用的 serverless 方案，把 serverless 标准化。目前参与的公司主要是 Google、Pivotal、IBM、Red Hat，2018年7月24日才刚刚对外发布，当前还处于快速发展的阶段。</p>
<p>这是 Google Cloud Platform 宣布 knative 时给出的介绍：</p>
<blockquote>
<p>Developed in close partnership with Pivotal, IBM, Red Hat, and SAP, Knative pushes Kubernetes-based computing forward by providing the building blocks you need to build and deploy modern, container-based serverless applications.</p>
</blockquote>
<p>可以看出，knative 是为了解决容器为核心的 serverless 应用的构建、部署和运行的问题。</p>
<p>serverless 的概念已经出现蛮久了，为了理解 serverless, 可以从应用开发者的角度来看，使用 serverless 框架之后，应用开发者的整个操作流程就变成了：</p>
<pre class=" language-bash"><code class="language-bash">~ <span class="token comment" spellcheck="true"># 编写 code 和 configuration 文件</span>

~ <span class="token comment" spellcheck="true"># faascli build</span>
~ <span class="token comment" spellcheck="true"># faascli deploy</span>
~ <span class="token comment" spellcheck="true"># curl http://myapp.com/hello</span>
hello, world from Awesome FaaS App<span class="token operator">!</span>
</code></pre>
<p>可以看到用户只需要编写代码（或者函数），以及配置文件（如何 build、运行以及访问等声明式信息），然后运行 build 和 deploy 就能把应用自动部署到集群（可以是公有云，也可以是私有的集群）。</p>
<p>其他事情都是 serverless 平台（比如这里的 knative）自动处理的，这些事情包括：</p>
<ul>
<li>自动完成代码到容器的构建</li>
<li>把应用（或者函数）和特定的事件进行绑定：当事件发生时，自动触发应用（或者函数）</li>
<li>网络的路由和流量控制</li>
<li>应用的自动伸缩</li>
</ul>
<p>和标准化的 FaaS 不同（只运行特定标准的 Function 代码），knative 期望能够运行所有的 workload : traditional application、function、container。</p>
<p>knative 建立在 kubernetes 和 istio 平台之上，使用 kubernetes 提供的容器管理能力（deployment、replicaset、和 pods等），以及 istio 提供的网络管理功能（ingress、LB、dynamic route等）。</p>
<p><img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxs8g0vej30qt09smxr.jpg" alt="knative with istio and kubernetes"></p>
<h2 id="knative-核心概念和原理"><a href="#knative-核心概念和原理" class="headerlink" title="knative 核心概念和原理"></a>knative 核心概念和原理</h2><p>为了实现 serverless 应用的管理，knative 把整个系统分成了三个部分：</p>
<ul>
<li>Build：构建系统，把用户定义的函数和应用 build 成容器镜像</li>
<li>Serving：服务系统，用来配置应用的路由、升级策略、自动扩缩容等功能</li>
<li>Eventing：事件系统，用来自动完成事件的绑定和触发</li>
</ul>
<h3 id="Build-构建系统"><a href="#Build-构建系统" class="headerlink" title="Build 构建系统"></a>Build 构建系统</h3><p>build 的功能是把用户的代码自动化构建成容器镜像，初次听起来很奇怪，有了 docker 之后有一个 Dockerfile 不就能构建容器了吗？为什么还需要一个新的 Build 系统？</p>
<p>Knative 的特别之处在于两点：一是它的构建完全是在 kubernetes 中进行的，和整个 kubernetes 生态结合更紧密；另外，它旨在提供一个通用的标准化的构建组件，可以作为其他更大系统中的一部分。</p>
<p>正如官方文档中的说的那样，是为了定义标准化、可移植、可重用、性能高效的构建方法：</p>
<blockquote>
<p>The goal of a Knative build is to provide a standard, portable, reusable, and performance optimized method for defining and running on-cluster container image builds.</p>
</blockquote>
<p>Knative 提供了 <code>Build</code> CRD 对象，让用户可以通过 yaml 文件定义构建过程。一个典型的 <code>Build</code> 配置文件如下：</p>
<pre class=" language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> build.knative.dev/v1alpha1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Build
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> example<span class="token punctuation">-</span>build
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">serviceAccountName</span><span class="token punctuation">:</span> build<span class="token punctuation">-</span>auth<span class="token punctuation">-</span>example
  <span class="token key atrule">source</span><span class="token punctuation">:</span>
    <span class="token key atrule">git</span><span class="token punctuation">:</span>
      <span class="token key atrule">url</span><span class="token punctuation">:</span> https<span class="token punctuation">:</span>//github.com/example/build<span class="token punctuation">-</span>example.git
      <span class="token key atrule">revision</span><span class="token punctuation">:</span> master
  <span class="token key atrule">steps</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> ubuntu<span class="token punctuation">-</span>example
    <span class="token key atrule">image</span><span class="token punctuation">:</span> ubuntu
    <span class="token key atrule">args</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"ubuntu-build-example"</span><span class="token punctuation">,</span> <span class="token string">"SECRETS-example.md"</span><span class="token punctuation">]</span>
  <span class="token key atrule">steps</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">image</span><span class="token punctuation">:</span> gcr.io/example<span class="token punctuation">-</span>builders/build<span class="token punctuation">-</span>example
    <span class="token key atrule">args</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'echo'</span><span class="token punctuation">,</span> <span class="token string">'hello-example'</span><span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">]</span>
</code></pre>
<p>其中，<code>serviceAccountName</code> 是构建过程中需要用到的密码和认证信息（比如连接到 git repo 的 SSH keys、push 镜像到 registry 的用户名和密码等）；<br><code>source</code> 是代码信息，比如这里的 git 地址和分支；<code>steps</code> 是真正运行过程中的各个步骤。<br>这个示例中的步骤只是作为 demo，真正的构建过程一般是 pull 代码、 build 镜像和 push镜像到 registry 等逻辑。</p>
<p>因为大部分的构建过程都是一致的，因此 knative 还提供了 <code>Build template</code> 的概念，<br>Build template 封装了预先定义好的构建过程（就是封装了上面的 <code>steps</code> 过程），并提供了非常简单的配置参数来使用。</p>
<p>使用 build template 构建容器镜像就更简单了，只需要提供代码的地址和镜像名字即可，比如下面是使用 Google kaniko 模板构建 github 源码的 yaml 文件（需要在代码根目录存在 Dockerfile 文件）：</p>
<pre class=" language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> build.knative.dev/v1alpha1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Build
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> kaniko<span class="token punctuation">-</span>build
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">serviceAccountName</span><span class="token punctuation">:</span> build<span class="token punctuation">-</span>bot
  <span class="token key atrule">source</span><span class="token punctuation">:</span>
    <span class="token key atrule">git</span><span class="token punctuation">:</span>
      <span class="token key atrule">url</span><span class="token punctuation">:</span> https<span class="token punctuation">:</span>//github.com/my<span class="token punctuation">-</span>user/my<span class="token punctuation">-</span>repo
      <span class="token key atrule">revision</span><span class="token punctuation">:</span> master
  <span class="token key atrule">template</span><span class="token punctuation">:</span>
    <span class="token key atrule">name</span><span class="token punctuation">:</span> kaniko
    <span class="token key atrule">arguments</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> IMAGE
      <span class="token key atrule">value</span><span class="token punctuation">:</span> us.gcr.io/my<span class="token punctuation">-</span>project/my<span class="token punctuation">-</span>app
</code></pre>
<h3 id="Serving：服务系统"><a href="#Serving：服务系统" class="headerlink" title="Serving：服务系统"></a>Serving：服务系统</h3><p>serving 的核心功能是让应用运行起来提供服务。</p>
<p>虽然听起来很简单，但这里包括了很多的事情：</p>
<ul>
<li>自动化启动和销毁容器</li>
<li>根据名字生成网络访问相关的 service、ingress 等对象</li>
<li>监控应用的请求，并自动扩缩容</li>
<li>支持蓝绿发布、回滚功能，方便应用发布流程</li>
</ul>
<p>knative serving 功能是基于 kubernetes 和 istio 开发的，它使用 kubernetes 来管理容器（deployment、pod），istio 来管理网络路由（VirtualService、DestinationRule）。</p>
<p>因为 kubernetes 和 istio 本身的概念非常多，理解和管理起来比较困难，knative 在此之上提供了更高一层的抽象（这些对应是基于 kubernetes 的 CRD 实现的）。这些抽象出来的概念对应的关系如下图：</p>
<p><img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxu9218oj31ck0qmwgu.jpg" alt="knative serving terminology"></p>
<ul>
<li>Configuration：应用的最新配置，也就是应用目前期望的状态，对应了 kubernetes 的容器管理（deployment）。每次应用升级都会更新 configuration，而 knative 也会保留历史版本的记录（图中的 revision），结合流量管理，knative 可以让多个不同的版本共同提供服务，方便蓝绿发布和滚动升级</li>
<li>Route：应用的路由规则，也就是进来的流量如何访问应用，对应了 istio 的流量管理（VirtualService）</li>
<li>Service：注意这里不是 kubernetes 中提供服务发现的那个 service，而是 knative 自定义的 CRD，它的全称目前是 <code>services.serving.knative.dev</code> 。单独控制 route 和 configuration 就能实现 serving 的所有功能，但knative 更推荐使用 Service 来管理，因为它会自动帮你管理 route 和 configuration</li>
</ul>
<p>一个 hello world 的 serving 配置如下所示：</p>
<pre class=" language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> serving.knative.dev/v1alpha1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Service
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> helloworld<span class="token punctuation">-</span>go
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> default
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">runLatest</span><span class="token punctuation">:</span>
    <span class="token key atrule">configuration</span><span class="token punctuation">:</span>
      <span class="token key atrule">revisionTemplate</span><span class="token punctuation">:</span>
        <span class="token key atrule">spec</span><span class="token punctuation">:</span>
          <span class="token key atrule">container</span><span class="token punctuation">:</span>
            <span class="token key atrule">image</span><span class="token punctuation">:</span> docker.io/<span class="token punctuation">{</span>username<span class="token punctuation">}</span>/helloworld<span class="token punctuation">-</span>go
            <span class="token key atrule">env</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> TARGET
              <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"Go Sample v1"</span>
</code></pre>
<p>看起来和 kubernetes 的 pod 定义非常类似，但是它会帮你管理 deployment、ingress、service discovery、auto scaling……从这个角度来看，可以认为 knative 提供了更高的抽象，自动帮你封装掉了 kubernetes 和 istio 的实现细节。</p>
<p>下面这张图介绍了 knative serving 各组件之间的关系：</p>
<p><img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNbRwgy1fum2swzqebj31j00to41f.jpg" alt="knative serving architecture"></p>
<ul>
<li>可以看到，每个 revision 对应了一组 deployment 管理的 pod</li>
<li>pod 会自动汇报 metrics 数据到 autoscaler，autoscaler 会根据请求量和资源使用情况修改 deployment 的 replicas 数量，从而实现自动扩缩容。serverless 一个重要的特定是它会 scale to 0 的，也就是当应用没有流量访问时，它会自动销毁所有的 pod</li>
<li>activator 比较有趣，它是为了处理 scale to 0 而出现的。当某个 revision 后面的 pod 缩容到 0 时，route 的流量会指向 activator，activator 接收到请求之后会自动拉起 pod，然后把流量转发过去</li>
<li>route 对象对应了 istio 的 DestinationRoute 和 VirtualService，决定了访问应用的流量如何路由</li>
</ul>
<h3 id="Eventing：事件系统"><a href="#Eventing：事件系统" class="headerlink" title="Eventing：事件系统"></a>Eventing：事件系统</h3><p>serving 系统实现的功能是让应用/函数能够运行起来，并且自动伸缩，那什么时候才会调用应用呢？除了我们熟悉的正常应用调用之外，serverless 最重要的是基于事件的触发机制，也就是说当某件事发生时，就触发某个特定的函数。</p>
<p>事件概念的出现，让函数和具体的调用方能够解耦。函数部署出来不用关心谁会调用它，而事件源触发也不用关心谁会处理它。</p>
<p>Note：目前 serverless 的产品和平台很多，每个地方支持的事件来源以及对事件的定义都是不同的（比如 AWS Lambda 支持很多自己产品的事件源）。Knative 自然也会定义自己的事件类型，除此之外，knative 还联合 CNCF 在做事件标准化的工作，目前的产出是 CloudEvents 这个项目。</p>
<p>为了让整个事件系统更有扩展性和通用性，knative 定义了很多事件相关的概念。我们先来介绍一下：</p>
<ul>
<li>EventSource：事件源，能够产生事件的外部系统</li>
<li>Feed：把某种类型的 EventType 和 EventSource 和对应的 Channel 绑定到一起</li>
<li>Channel：对消息实现的一层抽象，后端可以使用 kafka、RabbitMQ、Google PubSub 作为具体的实现。channel name 类似于消息集群中的 topic，可以用来解耦事件源和函数。事件发生后 sink 到某个 channel 中，然后 channel 中的数据会被后端的函数消费</li>
<li>Subscription：把 channel 和后端的函数绑定的一起，一个 channel 可以绑定到多个knative service</li>
</ul>
<p>它们之间的关系流程图如下：</p>
<p><img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNbRwgy1fum30a10ynj31jm0v2dkq.jpg" alt="knative eventing architecture"></p>
<p>Bus 是 knative 内部的事件存储层，用户可以选择自己感兴趣的实现，目前支持的方式有：Stub（在内存中实现的简单消息系统）、Kafka、Google PubSub。如果想要事件能够正常运行，必须在 knative 集群中安装其中一个 bus 实现方式。</p>
<p>有了 bus 之后，我们就可以监听外部的事件了。目前支持的事件源有三个：github（比如 merge 事件，push 事件等），kubernetes（events），Google PubSub（消息系统），后面还会不断接入更多的事件源。</p>
<p>如果要想监听对应的事件源，需要在 knative 中部署一个 source adaptor 的 pod，它负责从外部的系统中读取事件。</p>
<p>读取后的事件，会根据用户配置的 Feed 对象（里面包括了事件源和 channel 的对应关系），找到对应的 channel，然后把消息发送到这个 channel 中（channel 的消息最终是存储在后端的 bus 系统里的）。</p>
<p>然后，knative 会根据 subscription 的配置，不断从 channel 中读取事件，然后把事件作为参数调用对应的函数，从而完成了整个事件的流程。</p>
<h2 id="Knative-目前的状态"><a href="#Knative-目前的状态" class="headerlink" title="Knative 目前的状态"></a>Knative 目前的状态</h2><p>knative 是 2018 年 7月才刚刚对外开放，虽然内部已经开发一段时间，但是目前还处于非常早前的阶段（从支持的事件源和 bus就能看出来）。目前代码还不稳定，很多实现都是 hard-coded。</p>
<p>knative 也是脱产于 google 和 CNCF，因此整个社区运行方式和目标与之前的 kubernetes 以及 istio 非常相似。社区根据组件分成多个 Working Group，每个 Group 独立负责自己的功能，所有的开源活动（文档、视频、代码）都是开放的。另外，CloudEvents 作为 knative 依赖的标准，目标也是成为 CRI、CNI、CSI 这种类似的标准。</p>
<p>knative 社区目前非常活跃，以 <code>github.com/knative/serving</code> 项目为例，一个月已经有 600+ star，目前有 60+ contributor，900+ commits，而且入门的文档和教程都已经非常全面。</p>
<h2 id="Knative-应用场景和思考"><a href="#Knative-应用场景和思考" class="headerlink" title="Knative 应用场景和思考"></a>Knative 应用场景和思考</h2><p>knative 基于 kubernetes 和 istio 的 serverless 开源实现，目标是提供更高层次的抽象，让开发者无需关注基础设施（虚拟机或者容器，网络配置，容量规划），而专注于业务代码即可。更多关于 knative 的使用场景可以参考 AWS Lambda 或者其他相关的文档，这里不再赘述，主要讲讲 knative 目前的局限性或者问题：</p>
<h3 id="1-性能问题"><a href="#1-性能问题" class="headerlink" title="1. 性能问题"></a>1. 性能问题</h3><p>性能问题一直是 serverless 被人诟病的一点，也是目前它不能广泛用于应用服务上的决定性原因。互联网的应用大多数有高并发、高性能的要求，serverless 整个网络链路很长，容器启停需要额外的时间，还无法满足互联网应用的要求。</p>
<p>针对这一点，很多 serverless 框架也在不断地做改进，比如不断精简容器的启动时间、容器启动之后会做缓存等，比如 nuclio 就宣称自己的平台比 AWS Lambda 要快 10 倍以上。</p>
<p>相信随着 serverless 的不断演进，性能问题会不断优化，至于能不能达到互联网应用的要求，还要时间给我们答案。</p>
<h3 id="2-是否需要-istio-这一层？"><a href="#2-是否需要-istio-这一层？" class="headerlink" title="2. 是否需要 istio 这一层？"></a>2. 是否需要 istio 这一层？</h3><p>基于 kubernetes 的 serverless 组件非常多，比如 kubeless。但是基于 kubernetes 同时又基于 istio，目前 knative 还是第一个这么做的。</p>
<p>有些人的疑问在于，knative 真的有必要基于 istio 来做吗？对于这个问题，我个人的看法是必要的。</p>
<p>虽然 istio 才刚刚release 1.0 版本，但是它作为集群基础设施通用网络层的地位已经开始显露，相信在未来的发展中接受度会越来越大，并逐渐巩固自己的地位。虽然现阶段来说，很多人并不非常熟悉 istio 的情况，但是从长远角度来看，这一点将是 knative 的一个优势所在。</p>
<p>另外，基于 istio 构建自己的 serverless 服务，也符合目前软件行业不要重复造轮子的思路。istio 在集群的网络管理方面非常优秀（智能路由、负载均衡、蓝绿发布等），基于 istio 来做可以让 knative 不用重复工作就能直接使用 istio 提供的网络通用功能。</p>
<h3 id="3-系统复杂度"><a href="#3-系统复杂度" class="headerlink" title="3. 系统复杂度"></a>3. 系统复杂度</h3><p>这一点和上面类似，knative 下面已经有两个非常复杂的平台：kubernetes 和 istio。这两个平台的理解、构建、运维本身就很复杂，如今又加上 knative 整个平台，需要了解的概念都要几十个，更不要提落地过程中会遇到的各种问题。</p>
<p>对于公有云来说，kubernetes 和 istio 这些底层平台可以交给云供应商来维护（比如 google Function），但是对于内部构建来说，这无疑提高了整个技术门槛，对系统管理人员的要求更高。</p>
<p>如何安装部署整个集群？如何对集群做升级？出现问题怎么调试和追踪？怎么更好地和内部的系统对接？这些系统的最佳实践是什么？怎么做性能优化？所有这些问题都需要集群管理人员思考并落实。</p>
<h3 id="4-函数的可运维性？"><a href="#4-函数的可运维性？" class="headerlink" title="4. 函数的可运维性？"></a>4. 函数的可运维性？</h3><p>相对于编写微服务来说，单个函数的复杂度已经非常低，但是当非常多的函数需要共同工作的时候，如何管理这些函数就成了一个必须解决的问题。</p>
<ul>
<li>如何快速找到某个函数？</li>
<li>如何知道一个函数的功能是什么？接受的参数是什么？</li>
<li>怎么保证函数的升级不会破坏原有的功能？升级之后如何回滚？怎么记录函数的历史版本方面追溯？</li>
<li>当有多个函数需要同时工作的时候，怎么定义它们之间的关系？</li>
<li>函数出现问题的时候如何调试？</li>
</ul>
<p>对于函数的运维，一般的 serverless 平台（包括 knative）都提供了 logging、metrics、tracing 三个方面的功能。默认情况下，knative 使用 EFK（Elasticsearch、Fluent、Kibana）来收集、查找和分析日志；使用 prometheus + grafana 来收集和索引、展示 metrics 数据；使用 jaeger 来进行调用关系的 tracing。</p>
<p>针对 serverless 衍生出来的运维工具和平台还不够多，如何调试线上问题还没有看到非常好的解决方案。</p>
<h3 id="5-knative-成熟度"><a href="#5-knative-成熟度" class="headerlink" title="5. knative 成熟度"></a>5. knative 成熟度</h3><p>最后一点是关于 knative 成熟度的，前面已经提到，knative 目前刚出现不久。虽然整个框架和设计都已经搭好了，但是很多实现都比较初级。这里提几点来说：</p>
<ul>
<li>为了实现 autoscaling，knative 在每个 pod 中添加一个叫做 queue proxy 的代理，它会自动把请求的 metrics 发送给 autoscaler 组件作为参考。这样一来，整个网络链路上又多了一层，对整个性能势必会有影响，未来的打算是直接使用 envoy sidecar 来替换掉 queue proxy</li>
<li>支持的事件源和消息系统还很有限，外部事件只支持 github、kubernetes 和 Google PubSub。 这个问题可以慢慢扩展，knative 本身会实现很常用的事件类型，自定义的事件源用户可以自己实现</li>
<li>目前还没有函数的 pipeline 管理（类似 AWS Lambda Step Functions），多个函数如何协作并没有自己处理。虽然没有在官方文档中看到这方面的 roadmap，但是以后一定会有这方面的功能（不管是 knative 本身来做，还是社区作为工具补充来实现）</li>
</ul>
<p>这方面的问题都不是大事情，随着 knative 版本的迭代，在很快的时间都能够解决。</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul>
<li>Google Cloud Platform 宣布 Knative 发布的博客文章： <a href="https://cloudplatform.googleblog.com/2018/07/bringing-the-best-of-serverless-to-you.html" target="_blank" rel="noopener">Google Cloud Platform Blog: Bringing the best of serverless to you</a></li>
<li>the Newstack 上非常好的科普文章： <a href="https://thenewstack.io/knative-enables-portable-serverless-platforms-on-kubernetes-for-any-cloud/" target="_blank" rel="noopener">Knative Enables Portable Serverless Platforms on Kubernetes, for Any Cloud - The New Stack</a></li>
<li>Serving 的设计理念：<a href="https://docs.google.com/presentation/d/1CbwVC7W2JaSxRyltU8CS1bIsrIXu1RrZqvnlMlDaaJE/edit#slide=id.g32c674a9d1_0_5" target="_blank" rel="noopener">https://docs.google.com/presentation/d/1CbwVC7W2JaSxRyltU8CS1bIsrIXu1RrZqvnlMlDaaJE/edit#slide=id.g32c674a9d1_0_5</a></li>
<li>knative 官方文档：<a href="https://github.com/knative/docs" target="_blank" rel="noopener">GitHub - knative/docs: Documentation for users of Knative components</a></li>
<li>Google Cloud Next 2018 大会上宣布 knative 的视频 presentation：  <a href="https://www.youtube.com/watch?v=LtELzpw1l1M&amp;t=1s&amp;list=PLBgogxgQVM9v0xG0QTFQ5PTbNrj8uGSS-&amp;index=105" target="_blank" rel="noopener">Kubernetes, Serverless, and You (Cloud Next ’18) - YouTube</a></li>
<li><a href="https://cloud.google.com/knative/" target="_blank" rel="noopener">Google Cloud Knative 产品页面，目前只有最简单的介绍和文档链接</a></li>
</ul>

                </div>
            </section>
        </article>
    </div>
    
<nav class="pagination">
    
    
    <a class="prev-post" title="什么是 istio" href="/2018/08/26/what-is-istio/">
        ← 什么是 istio
    </a>
    
    <span class="prev-next-post">•</span>
    
    <a class="next-post" title="kubernetes 资源管理概述" href="/2018/06/25/kubernetes-resource-management/">
        kubernetes 资源管理概述 →
    </a>
    
    
</nav>

    <div class="inner">
    <!-- Begin Mailchimp Signup Form -->
    <link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
    <style type="text/css">
    	#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
    	/* Add your own Mailchimp form style overrides in your site stylesheet or in this style block.
    	   We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
    </style>
    <div id="mc_embed_signup">
    <form action="https://cizixs.us7.list-manage.com/subscribe/post?u=2d561b8dea52d73a2e05e6dcb&amp;id=5c710f135b" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
        <div id="mc_embed_signup_scroll">
    	<h2>订阅本博客，第一时间收到文章更新</h2>
    <div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
    <div class="mc-field-group">
    	<label for="mce-EMAIL">邮件地址  <span class="asterisk">*</span>
    </label>
    	<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
    </div>
    	<div id="mce-responses" class="clear">
    		<div class="response" id="mce-error-response" style="display:none"></div>
    		<div class="response" id="mce-success-response" style="display:none"></div>
    	</div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
        <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_2d561b8dea52d73a2e05e6dcb_5c710f135b" tabindex="-1" value=""></div>
        <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
        </div>
    </form>
    </div>
    <script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
    <!--End mc_embed_signup-->
    </div>

    <div class="inner">
        <div id="disqus_thread"></div>
    </div>

    
</main>

<div class="t-g-control">
    <div class="gotop">
        <svg class="icon" width="32px" height="32px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M793.024 710.272a32 32 0 1 0 45.952-44.544l-310.304-320a32 32 0 0 0-46.4 0.48l-297.696 320a32 32 0 0 0 46.848 43.584l274.752-295.328 286.848 295.808z" fill="#8a8a8a" /></svg>
    </div>
    <div class="toc-control">
        <svg class="icon toc-icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M779.776 480h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M779.776 672h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M256 288a32 32 0 1 0 0 64 32 32 0 0 0 0-64M392.576 352h387.2a32 32 0 0 0 0-64h-387.2a32 32 0 0 0 0 64M256 480a32 32 0 1 0 0 64 32 32 0 0 0 0-64M256 672a32 32 0 1 0 0 64 32 32 0 0 0 0-64" fill="#8a8a8a" /></svg>
        <svg class="icon toc-close" style="display: none;" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 960c-247.039484 0-448-200.960516-448-448S264.960516 64 512 64 960 264.960516 960 512 759.039484 960 512 960zM512 128.287273c-211.584464 0-383.712727 172.128262-383.712727 383.712727 0 211.551781 172.128262 383.712727 383.712727 383.712727 211.551781 0 383.712727-172.159226 383.712727-383.712727C895.712727 300.415536 723.551781 128.287273 512 128.287273z" fill="#8a8a8a" /><path d="M557.05545 513.376159l138.367639-136.864185c12.576374-12.416396 12.672705-32.671738 0.25631-45.248112s-32.704421-12.672705-45.248112-0.25631l-138.560301 137.024163-136.447897-136.864185c-12.512727-12.512727-32.735385-12.576374-45.248112-0.063647-12.512727 12.480043-12.54369 32.735385-0.063647 45.248112l136.255235 136.671523-137.376804 135.904314c-12.576374 12.447359-12.672705 32.671738-0.25631 45.248112 6.271845 6.335493 14.496116 9.504099 22.751351 9.504099 8.12794 0 16.25588-3.103239 22.496761-9.247789l137.567746-136.064292 138.687596 139.136568c6.240882 6.271845 14.432469 9.407768 22.65674 9.407768 8.191587 0 16.352211-3.135923 22.591372-9.34412 12.512727-12.480043 12.54369-32.704421 0.063647-45.248112L557.05545 513.376159z" fill="#8a8a8a" /></svg>
    </div>
    <div class="gobottom">
        <svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M231.424 346.208a32 32 0 0 0-46.848 43.584l297.696 320a32 32 0 0 0 46.4 0.48l310.304-320a32 32 0 1 0-45.952-44.544l-286.848 295.808-274.752-295.36z" fill="#8a8a8a" /></svg>
    </div>
</div>
<div class="toc-main" style="right: -100%">
    <div class="post-toc">
        <span>TOC</span>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#什么是-Knative？"><span class="toc-text">什么是 Knative？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#knative-核心概念和原理"><span class="toc-text">knative 核心概念和原理</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Build-构建系统"><span class="toc-text">Build 构建系统</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Serving：服务系统"><span class="toc-text">Serving：服务系统</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Eventing：事件系统"><span class="toc-text">Eventing：事件系统</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Knative-目前的状态"><span class="toc-text">Knative 目前的状态</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Knative-应用场景和思考"><span class="toc-text">Knative 应用场景和思考</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-性能问题"><span class="toc-text">1. 性能问题</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-是否需要-istio-这一层？"><span class="toc-text">2. 是否需要 istio 这一层？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-系统复杂度"><span class="toc-text">3. 系统复杂度</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-函数的可运维性？"><span class="toc-text">4. 函数的可运维性？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-knative-成熟度"><span class="toc-text">5. knative 成熟度</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#参考资料"><span class="toc-text">参考资料</span></a></li></ol>
    </div>
</div>



        

<aside class="read-next outer">
    <div class="inner">
        <div class="read-next-feed">
            
            

<article class="read-next-card"  style="background-image: url(https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxcn9ft3j318w0txdo6.jpg)"  >
  <header class="read-next-card-header">
    <small class="read-next-card-header-sitetitle">&mdash; Cizixs Write Here &mdash;</small>
    <h3 class="read-next-card-header-title">Recent Posts</h3>
  </header>
  <div class="read-next-divider">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M13 14.5s2 3 5 3 5.5-2.463 5.5-5.5S21 6.5 18 6.5c-5 0-7 11-12 11C2.962 17.5.5 15.037.5 12S3 6.5 6 6.5s4.5 3.5 4.5 3.5"/>
    </svg>
  </div>
  <div class="read-next-card-content">
    <ul>
      
      
      
      <li>
        <a href="/2018/08/26/what-is-istio/">什么是 istio</a>
      </li>
      
      
      
      <li>
        <a href="/2018/08/25/knative-serverless-platform/">serverless 平台 knative 简介</a>
      </li>
      
      
      
      <li>
        <a href="/2018/06/25/kubernetes-resource-management/">kubernetes 资源管理概述</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/24/use-prometheus-and-grafana-to-monitor-linux-machine/">使用 promethues 和 grafana 监控自己的 linux 机器</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/13/linux-udp-packet-drop-debug/">linux 系统 UDP 丢包问题分析思路</a>
      </li>
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    </ul>
  </div>
  <footer class="read-next-card-footer">
    <a href="/archives">  MORE  → </a>
  </footer>
</article>


            
            
            
        </div>
    </div>
</aside>


<footer class="site-footer outer">

	<div class="site-footer-content inner">
		<section class="copyright">
			<a href="/" title="Cizixs Write Here">Cizixs Write Here</a>
			&copy; 2019
		</section>
		<nav class="site-footer-nav">
			
            <a href="https://hexo.io" title="Hexo" target="_blank" rel="noopener">Hexo</a>
            <a href="https://github.com/xzhih/hexo-theme-casper" title="Casper" target="_blank" rel="noopener">Casper</a>
        </nav>
    </div>
</footer>






<div class="floating-header" >
	<div class="floating-header-logo">
        <a href="/" title="Cizixs Write Here">
			
                <img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg" alt="Cizixs Write Here icon" />
			
            <span>Cizixs Write Here</span>
        </a>
    </div>
    <span class="floating-header-divider">&mdash;</span>
    <div class="floating-header-title">serverless 平台 knative 简介</div>
    <progress class="progress" value="0">
        <div class="progress-container">
            <span class="progress-bar"></span>
        </div>
    </progress>
</div>
<script>
   $(document).ready(function () {
    var progressBar = document.querySelector('progress');
    var header = document.querySelector('.floating-header');
    var title = document.querySelector('.post-full-title');
    var lastScrollY = window.scrollY;
    var lastWindowHeight = window.innerHeight;
    var lastDocumentHeight = $(document).height();
    var ticking = false;

    function onScroll() {
        lastScrollY = window.scrollY;
        requestTick();
    }
    function requestTick() {
        if (!ticking) {
            requestAnimationFrame(update);
        }
        ticking = true;
    }
    function update() {
        var rect = title.getBoundingClientRect();
        var trigger = rect.top + window.scrollY;
        var triggerOffset = title.offsetHeight + 35;
        var progressMax = lastDocumentHeight - lastWindowHeight;
            // show/hide floating header
            if (lastScrollY >= trigger + triggerOffset) {
                header.classList.add('floating-active');
            } else {
                header.classList.remove('floating-active');
            }
            progressBar.setAttribute('max', progressMax);
            progressBar.setAttribute('value', lastScrollY);
            ticking = false;
        }

        window.addEventListener('scroll', onScroll, {passive: true});
        update();

        // TOC
        var width = $('.toc-main').width();
        $('.toc-control').click(function () {
            if ($('.t-g-control').css('width')=="50px") {
                if ($('.t-g-control').css('right')=="0px") {
                    $('.t-g-control').animate({right: width}, "slow");
                    $('.toc-main').animate({right: 0}, "slow");
                    toc_icon()
                } else {
                    $('.t-g-control').animate({right: 0}, "slow");
                    $('.toc-main').animate({right: -width}, "slow");
                    toc_icon()
                }
            } else {
                if ($('.toc-main').css('right')=="0px") {
                    $('.toc-main').slideToggle("fast", toc_icon());
                } else {
                    $('.toc-main').css('right', '0px');
                    toc_icon()
                }
            }
        })

        function toc_icon() {
            if ($('.toc-icon').css('display')=="none") {
                $('.toc-close').hide();
                $('.toc-icon').show();
            } else {
                $('.toc-icon').hide();
                $('.toc-close').show();
            }
        }

        $('.gotop').click(function(){
            $('html,body').animate({scrollTop:$('.post-full-header').offset().top}, 800);
        });
        $('.gobottom').click(function () {
            $('html,body').animate({scrollTop:$('.pagination').offset().top}, 800);
        });

        // highlight
        // https://highlightjs.org
        $('pre code').each(function(i, block) {
            hljs.highlightBlock(block);
        });
        $('td.code').each(function(i, block) {
            hljs.highlightBlock(block);
        });

        console.log("this theme is from https://github.com/xzhih/hexo-theme-casper")
    });
</script>



<link rel="stylesheet" href="https://cdn.staticfile.org/lightgallery/1.3.9/css/lightgallery.min.css">



<script src="https://cdn.staticfile.org/lightgallery/1.3.9/js/lightgallery.min.js"></script>


<script>
	$(function () {
		var postImg = $('#lightgallery').find('img');
		postImg.addClass('post-img');
		postImg.each(function () {
			var imgSrc = $(this).attr('src');
			$(this).attr('data-src', imgSrc);
		});
		$('#lightgallery').lightGallery({selector: '.post-img'});
	});
</script>



<script>

/**
*  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
*  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/

var disqus_config = function () {
this.page.url = 'http://cizixs.com/2018/08/25/knative-serverless-platform/';  // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = 'http://cizixs.com/2018/08/25/knative-serverless-platform/'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};

(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://cizixs.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
                            


    </div>
</body>
</html>
